package game;

import java.awt.Point;
import java.util.*;

/**
 * <p>The Knight's Tour is a unique game where one <tt>Knight</tt> begins at an arbitrary location on the board and moves 
 * around the board touching each square only once. Once all the squares have been touched only once the game is complete.</p>
 * 
 * @author Nicole Waldrum
 * @date January 30, 2010
 * @version 1.0
 * 
 * @author Mark Kelly
 * @date February 20, 2010
 * @version 2.0
 * 
 * @author Mark Kelly
 * @date March 9, 2010
 * @version 3.0
 *
 */
public class KnightTour extends GameType {
	// InstanceVariables
    private Set<Point> usedSquares;
    private Knight knight;
    
    /**
	 * <p>Creates a new instance of <tt>KnightTour</tt>.</p>
	 */
	public KnightTour() {
		super();
		usedSquares = new HashSet<Point>();
	}

	/**
	 * {@inheritDoc}
	 * 
	 * <p>In the case of the Knight's tour, the new position of the <tt>Knight</tt> is added to the 'blacklist' of spaces that the <tt>Knight</tt> has used.</p>
	 */
	public void pieceMoved (Piece p, ChessBoard b) {
		usedSquares.add(p.getLocation());
		
		if (hasWon(p.getTeam())) {
			state.stateChanged(state);
			state.notifyGameWon(p.getTeam());
		}
	}

	/**
	 * {@inheritDoc}
	 * 
	 * <p>In the case of the Knight's Tour, a single <tt>Knight</tt> is placed on the board.</p>
	 */
	@Override
	public void setupBoard() {
		ChessBoard board = new ChessBoard(boardSize);
		
		Point start = new Point (1, 1);
		
		knight = new Knight(start, Team.BLACK);
		board.addPiece(knight);
		
		usedSquares.add(start);
		
		state.setBoard(board);
	}
	
	/**
	 * {@inheritDoc}
	 * 
	 * <p>In the case of the Knight's Tour, each square must have been visited once.</p>
	 */
	@Override
	public boolean hasWon(Team team) {
		return (usedSquares.size() == 64);
	}
	
	/**
	 * {@inheritDoc}
	 * 
	 * <p>In the case of the Knight's Tour, the square cannot have been previously visited by the <tt>Knight</tt>.</p>
	 */
	public boolean isValidMove(Piece piece, Point dest){
		return !(usedSquares.contains(dest));
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean movePiece(Point start, Point dest) {
		ChessBoard board = state.getBoard();

		// this will leave a trail of Knights of the opposite colour
		Knight oldKnight = new Knight(knight.getLocation(), knight.getTeam().other());
		
		// check if its a valid move and if the pawn exception is in effect
		if (state.isValidMove(knight, dest)) {
			knight = new Knight(dest, knight.getTeam());
			board.movePiece(knight, dest);
			board.movePiece(oldKnight, oldKnight.getLocation());
			state.pieceMoved(knight, board);
			return true;
		}

		// invalid move
		return false;
	}
}
